package com.base.cn.platform.os.common.utils;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 数据工具类
 *
 * @author s.li
 * @create 2018-02-08 11:18
 */
public class DataUtil extends BaseUtil {

    /**
     * 验证ID不为空，且不大于0
     *
     * @param id 要验证的ID属性
     * @return true验证通过，false验证失败
     */
    public static boolean idIsNotNull(BigDecimal id) {
        if (id != null && id.compareTo(new BigDecimal(0)) != 0) {
            return true;
        }
        return false;
    }

    /**
     * 验证给定数字是否大于0
     *
     * @param number 数字
     * @return {@code true} 不为null且大于0
     */
    public static boolean isPositive(Number number) {
        return number != null && number.doubleValue() > 0;
    }

    /**
     * 验证给定数字是否为非负数
     *
     * @param number 数字
     * @return {code 0} 不为null且大于等于0
     */
    public static boolean isNonNegative(Number number) {
        return number != null && number.intValue() >= 0;
    }

    /**
     * 过滤字符串中的非数字
     *
     * @param ids ids
     * @return ids串中数字组成的ids
     */
    public static String filterNotNumberStr(String ids) {
        if (StringUtils.isEmpty(ids)) {
            return "";
        }
        return Stream.of(ids.split(","))
                .filter(StringUtils::isNumber)
                .distinct()
                .collect(Collectors.joining(","));
    }

    /**
     * 将输入元素按指定的key映射函数分组
     *
     * @param collection 输入元素组成的{@link Collection}
     * @param classifier 将输入元素按key分组的{@link Function}
     * @param <E>        输入的元素的类型
     * @param <K>        key的类型
     * @return 分组后的输入元素
     * @see Collectors#groupingBy(Function)
     */
    public static <E, K> Map<K, List<E>> grouping(Collection<E> collection, Function<E, K> classifier) {
        if (ObjectUtils.isEmpty(collection)) {
            return new HashMap<>();
        }
        return collection.stream().collect(Collectors.groupingBy(classifier));
    }

    /**
     * 将输入元素按指定的key映射函数, value为输入元素本身转换为{@link Map}
     *
     * @param collection 输入元素组成的{@link Collection}
     * @param keyMapper  将输入元素映射为key的{@link Function}
     * @param <E>        输入元素类型
     * @param <K>        key的类型
     * @return 按指定key映射函数, value为输入元素本身转换的map
     * @see #toMap(Collection, Function, Function)
     * @see Collectors#toMap(Function, Function)
     */
    public static <E, K> Map<K, E> toMap(Collection<E> collection, Function<E, K> keyMapper) {
        return toMap(collection, keyMapper, Function.identity());
    }

    /**
     * 将输入元素按指定的key-value映射函数转换为{@link Map}
     *
     * @param collection  输入元素组成的{@link Collection}
     * @param keyMapper   将输入元素映射为key的{@link Function}
     * @param valueMapper 将输入元素映射为value的{@link Function}
     * @param <E>         输入元素类型
     * @param <K>         key的类型
     * @param <V>         value的类型
     * @return 按指定key映射函数转换的map
     * @see #toMap(Collection, Function)
     * @see Collectors#toMap(Function, Function)
     */
    public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> keyMapper, Function<E, V> valueMapper) {
        if (ObjectUtils.isEmpty(collection)) {
            return new HashMap<>();
        }
        return collection.stream().collect(Collectors.toMap(keyMapper, valueMapper));
    }

    /**
     * 根据提供的{@link Function}拼接输入元素的属性
     *
     * @param collection 输入元素组成的{@link Collection}
     * @param mapper     输入元素属性映射函数
     * @param <E>        输入元素的类型
     * @return 拼接后的字符串
     */
    public static <E> String joining(Collection<E> collection, Function<E, ?> mapper) {
        if (ObjectUtils.isEmpty(collection)) {
            return "";
        }
        return collection.stream()
                .map(mapper)
                .filter(Objects::nonNull)
                .map(String::valueOf)
                .filter(StringUtils::isNotEmpty)
                .distinct()
                .collect(Collectors.joining(","));
    }

    /**
     * 将输入元素映射为指定输出类型的{@link List}
     *
     * @param collection 输入元素组成的{@link Collection}
     * @param mapper     输入元素属性映射函数
     * @param <E>        输入元素类型
     * @param <R>        输出元素类型
     * @return 输出元素组成的list
     * @see Stream#map(Function)
     */
    public static <E, R> List<R> map(Collection<E> collection, Function<E, R> mapper) {
        if (ObjectUtils.isEmpty(collection)) {
            return Collections.emptyList();
        }
        return collection.stream()
                .map(mapper)
                .collect(Collectors.toList());
    }

    /**
     * 将输入元素按指定的key映射函数分组并统计每组的数量
     *
     * @param collection 输入元素组成的{@link Collection}
     * @param classifier 将输入元素按key分组的{@link Function}
     * @param <E>        输入的元素的类型
     * @param <K>        key的类型
     * @return 分组后的输入元素
     * @see #grouping(Collection, Function)
     * @see Collectors#groupingBy(Function)
     */
    public static <E, K> Map<K, Long> counting(Collection<E> collection, Function<E, K> classifier) {
        if (ObjectUtils.isEmpty(collection)) {
            return new HashMap<>();
        }
        return collection.stream()
                .collect(Collectors.groupingBy(classifier,
                        Collectors.counting()));
    }

    /**
     * 将输入元素组成的集合筛选出符合指定的谓词的输入元素集合
     *
     * @param collection 输入元素组成的{@link Collection}
     * @param predicate  筛选输入元素的{@link Predicate 谓词}
     * @param <E>        输入的元素的类型
     * @return 筛选后的输入元素集合
     */
    public static <E> List<E> filter(Collection<E> collection, Predicate<E> predicate) {
        if (ObjectUtils.isEmpty(collection)) {
            return new LinkedList<>();
        }
        return collection.stream()
                .filter(Objects::nonNull)
                .filter(predicate)
                .collect(Collectors.toList());
    }

}
